package com.wilmar.designer.service;

import com.wilmar.designer.util.XsltUtils;
import com.wilmar.process.core.services.api.ISystemProcessDefinitionService;
import com.wilmar.process.entity.ProcessReleaseNotes;
import com.wilmar.process.entity.User;
import org.springframework.core.io.Resource;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * RestFul service for designer.
 * 
 * User: Sean
 * Date: Dec 31, 2009
 * Time: 10:28:47 AM
 */
public class DocumentService {


    private ISystemProcessDefinitionService systemProcessDefinitionService;
    private User user;

    public String flowSrcRepo = "/tmp";

    public DocumentService(Resource flowSrcRepoResource) throws IOException {
        flowSrcRepoResource.getFile().mkdirs();
        flowSrcRepo = flowSrcRepoResource.getFile().getAbsolutePath();
    }

    public String generateRepoFileName(String id, String subpfix) {
        return flowSrcRepo + File.separator + id + subpfix;
    }

    public void save(String id, String content, byte[] thumb) throws IOException, TransformerException {

        OutputStream thumbOutputStream = new FileOutputStream(generateRepoFileName(id, ".png"));
        thumbOutputStream.write(thumb);
        thumbOutputStream.close();

        Writer contentWriter = new FileWriter(generateRepoFileName(id, ".xml"));
        contentWriter.append(content);
        contentWriter.close();

        deploy(id);
    }

    public String load(String id) throws IOException {
        StringBuilder sb = new StringBuilder();

        Reader contentReader = new FileReader(generateRepoFileName(id, ".xml"));
        BufferedReader br = new BufferedReader(contentReader);

        String line = br.readLine();
        while (line != null) {
            sb.append(line).append(System.getProperty("line.separator"));

            line = br.readLine();
        }

        return sb.toString();
    }

    public void transform(String id) throws IOException, TransformerException {
        Reader contentReader = new FileReader(generateRepoFileName(id, ".xml"));
        Writer contentWriter = new FileWriter(generateRepoFileName(id, ".jpdl.xml"));
        Reader xsltReader = new FileReader("/Users/Sean/Desktop/Work/Projects/workflow-designer-server/src/jbpm.xsl");

        Transformer transformer = XsltUtils.createTransformer(xsltReader);
        transformer.setParameter("documentId", id);
        transformer.transform(new StreamSource(contentReader), new StreamResult(contentWriter));
    }

    public void zip(String id) throws IOException {
        String[] fileNames = {
                generateRepoFileName(id, ".jpdl.xml"),
                generateRepoFileName(id, ".png")
        };

        byte[] buf = new byte[10240];
        int len;

        String packageFile = generateRepoFileName(id, ".zip");

        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(packageFile, false));
        for(String fileName:fileNames) {
            File file = new File(fileName);

            out.putNextEntry(new ZipEntry(file.getName()));

            FileInputStream in = new FileInputStream(file);
            while((len =in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

            out.closeEntry();
            in.close();
        }

        out.close();
    }

    public void deploy(String id) throws IOException, TransformerException {
        transform(id);
        zip(id);

        File packageFile = new File(generateRepoFileName(id, ".zip"));

        ProcessReleaseNotes processReleaseNotes= new ProcessReleaseNotes();
        processReleaseNotes.setOuterSystem(user.getOuterSystem());
        processReleaseNotes.setCreatePerson(user.getName());

        getSystemProcessDefinitionService().deployProcessDefinition(packageFile, processReleaseNotes);
    }

    public ISystemProcessDefinitionService getSystemProcessDefinitionService() {
        return systemProcessDefinitionService;
    }

    public void setSystemProcessDefinitionService(ISystemProcessDefinitionService systemProcessDefinitionService) {
        this.systemProcessDefinitionService = systemProcessDefinitionService;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
